package process

import (
	"encoding/json"
	"fmt"
	"go_code/chatroom/client/message"
	"go_code/chatroom/client/model"
	"go_code/chatroom/client/utils"
	"net"
	"os"
)

type UserProcess struct {
	Conn net.Conn
}

func (up *UserProcess) Register(userId int64, username string, password string) (err error) {
	defer func() {
		err = up.Conn.Close()
		if err != nil {
			return
		}
	}()

	var msg *message.Message
	var registerMsg *message.RegisterReqMessage
	var responseMsg *message.ResponseMessage

	registerMsg = &message.RegisterReqMessage{
		User: message.User{
			UserId: userId,
			Username: username,
			Password: password,
		},
	}

	marshal, _ := json.Marshal(registerMsg)
	msg = &message.Message{
		Type: message.TypeRegisterReq,
		Data: string(marshal),
	}

	t := &utils.Transport{
		Conn: up.Conn,
	}

	err = t.WritePkg(msg)
	if err != nil {
		fmt.Println("Client Register 传输数据错误", err)
		return
	}

	msg, err = t.ReadPkg()
	if err != nil {
		fmt.Println("Client Register 读取消息错误", err)
		return
	}

	_ = json.Unmarshal([]byte(msg.Data), &responseMsg)
	if responseMsg.Code == 200 {
		fmt.Println("注册成功，请重新登录吧!!!")
		os.Exit(0)
	} else {
		fmt.Println(responseMsg.Error)
		os.Exit(1)
	}

	return
}

func (up *UserProcess) Login(userId int64, password string) (err error) {
	var msg *message.Message
	var loginReqMsg *message.LoginReqMessage
	var loginResMsg *message.LoginResMessage

	loginReqMsg = &message.LoginReqMessage{
		User: message.User{
			UserId: userId,
			Password: password,
		},
	}

	marshal, _ := json.Marshal(loginReqMsg)
	msg = &message.Message{
		Type: message.TypeLoginReq,
		Data: string(marshal),
	}

	t := &utils.Transport{
		Conn: up.Conn,
	}
	fmt.Println(111, *msg)
	_ = t.WritePkg(msg)

	msg, _ = t.ReadPkg()
	_ = json.Unmarshal([]byte(msg.Data), &loginResMsg)

	if loginResMsg.Code == 200 {
		fmt.Println("登录成功")
		// var userStatus *message.UserStatusMessage
		var user *model.User

		// 当前登录用户需要一个连接来给服务端发送消息
		currentUser = &model.CurrentUser {
			UserId: userId,
			Status: message.UserStatusOnline,
			Conn: up.Conn,
		}

		// 我自己登录成功后，服务端会把在线的 userId 切片发给我
		// 在我本地维护在线用户，如果有用户下线或上线，会在 keepConnection 方法中更新
		for _, v := range loginResMsg.UserIds {
			user = &model.User{
				UserId: v,
				Status: message.UserStatusOnline,
			}

			onlineUsers[v] = user
		}

		// 我们需要再客户端启动一个协程
		// 该协程保持和服务端的通讯，如果服务器有数据推送...
		go keepConnection(up.Conn)

		for {
			showMenu()
		}
	} else {
		fmt.Println(loginResMsg.Error)
	}

	return
}

func keepConnection(conn net.Conn) {
	t := &utils.Transport{
		Conn: conn,
	}

	for {
		msg, err := t.ReadPkg()
		if err != nil {
			return
		}

		switch msg.Type {
		case message.NotifyUserStatus:
			updateUserStatus(msg)
		case message.TypeSmsReq:
			outputGroupMessage(msg)
		default:
			fmt.Println("未知的类型")
		}
	}
}